import { _classExample, Singleton } from './BaseManager';
import { Component } from 'cc';

export interface IRecycle {
  reuse(...args: unknown[]);
  unuse();
}

export class NodeRecycle extends Component implements IRecycle {
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  reuse(...args: unknown[]) {}
  unuse() {}
}

export abstract class BaseRecycle implements IRecycle {
  abstract reuse(...args: unknown[]);
  abstract unuse();

  static pop<T extends BaseRecycle>(this: _classExample<T>, ...args: unknown[]): T {
    return PoolManager.Ins().popObj(this, ...args);
  }

  release<T extends BaseRecycle>(this: T) {
    PoolManager.Ins().pushObj(this);
  }
}

export class PoolManager extends Singleton {
  private _objectPool: Map<string, Array<BaseRecycle>> = new Map<string, Array<BaseRecycle>>();
  /**
   * 从对象池中获取指定类型的obj
   * @param type 指定的类型
   * @returns 实例化后的obj
   */
  popObj<T extends BaseRecycle>(type: _classExample<T>, ...args: unknown[]): T {
    const pool = this._objectPool.get(type.name);
    if (pool == null || pool.length <= 0) {
      const obj = new type();
      obj.reuse(...args);
      return obj;
    } else {
      const obj = this._objectPool.get(type.name).pop();
      obj.reuse(...args);
      return obj as T;
    }
  }

  /**
   * 把指定类型的obj放回对象池
   * @param object 指定的obj
   */
  pushObj<T extends BaseRecycle>(object: T) {
    const className = object.constructor.name;
    if (!this._objectPool.has(className)) this._objectPool.set(className, new Array<T>());
    object.unuse();
    this._objectPool.get(className).push(object);
  }
}
